// 十六进制颜色转为 RGB
// colorRgb("#fff") : [255,255,255]
export const colorRgb = hex => {
    let color = hex.toLowerCase();
    //十六进制颜色值的正则表达式
    const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
    // 如果是 16 进制颜色
    if (color && reg.test(color)) {
        if (color.length === 4) {
            var colorNew = "#";
            for (var i = 1; i < 4; i += 1) {
                colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1));
            }
            color = colorNew;
        }
        //处理六位的颜色值
        const result = [];
        for (var i = 1; i < 7; i += 2) {
            result.push(parseInt("0x" + color.slice(i, i + 2)));
        }
        return result;
    } else {
        return [0, 0, 0];
    }
};

// rgb 转为十六进制颜色
// colorHex('rgb(255,255,255)') : "#ffffff"
export const colorHex = color => {
    const [r, g, b] = color;
    const hex = [r, g, b].map(i => {
        var hex = Number(i).toString(16);
        if (hex.length < 2) {
            return "0" + hex;
        } else {
            return hex.substring(0, 2);
        }
    });

    return "#" + hex.join("");
};

// 合并颜色
export const shadeColor = (color, percent) => {
    const num = parseInt(color.slice(1), 16),
        amt = Math.round(2.55 * percent),
        R = (num >> 16) + amt,
        G = ((num >> 8) & 0x00ff) + amt,
        B = (num & 0x0000ff) + amt;
    return "#" + (0x1000000 + (R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 + (G < 255 ? (G < 1 ? 0 : G) : 255) * 0x100 + (B < 255 ? (B < 1 ? 0 : B) : 255)).toString(16).slice(1);
};

// HSL 是对色相H(hue)、饱和度S(saturation)、亮度L(lightness)的处理得到颜色的一种模型。
// 色相(H)：
// 色相、色调，代表人眼所能看到的不同的颜色，本质就是一种颜色。与 HSV(B) 模型中的 H 概念相同。
// 色相的定义中，许多的颜色分布在一个圆环上，取值范围则是 0-360度，每个角度代表着一种颜色。
// 在HSL和HSV的模型中，色相是以六大主色为基础，他们分别按 60 度的间隔排列在圆环上。这六大主色分别是：360°/0°红、60°黄、120°绿、180°青、240°蓝、300°洋红。
// 而在前端进行处理时，常常把圆环处理成长方形的色块，通过颜色的线性渐变方式进行分段处理，角度换算成一定的比例，如下所示：
// 饱和度(S)：
// 饱和度是指颜色的强度或纯度，使用 0 ~ 100% 的百分比来度量。
// 表示色相中颜色成分所占的比例，数值越大，颜色中的灰色越少，颜色越鲜艳，呈现的是一种从灰色到色相颜色的变化。
// 亮度(L)：
// 表现颜色的明暗程度，使用 0 ~ 100% 的百分比来度量。
// 反映色彩中混入的黑白两色，50% 处只有纯色，小于 50% 时，数值越小混入的黑色越多，越接近于黑色；大于 50% 时，数值越大混入的白色越多，越接近于白色。
// L最大时必为白色，L最小时必为黑色。
// 体现的是从黑色到色相(H)选择颜色再到白色的过渡。
// rgb 转 hsl
// 这两个过程中，由于取整去除了小数位，并不是完全可逆的，可能存在个别个位数的差值,虽有些微差别，但在页面颜色显示上基本没分别，因为人眼分辨不出来。
export const rgbToHsl = (red, green, blue) => {
    red = red / 255;
    green = green / 255;
    blue = blue / 255;

    let hue = (saturation = lightness = 0);
    const max = Math.max(red, green, blue);
    const min = Math.min(red, green, blue);
    const diff = max - min;
    const sum = max + min;

    lightness = sum / 2;

    if (diff) {
        saturation = lightness > 0.5 ? diff / (2 - sum) : diff / sum;
        switch (max) {
            case red:
                hue = (green - blue) / diff + (green < blue ? 6 : 0);
                break;
            case green:
                hue = (blue - red) / diff + 2;
                break;
            case blue:
                hue = (red - green) / diff + 4;
                break;
        }
        hue = hue / 6;
    }

    hue = Math.round(hue * 360);
    saturation = Math.round(saturation * 100);
    lightness = Math.round(lightness * 100);
    return [hue, saturation, lightness];
};

// hsl 转 rgb
export const hslToRgb = (hue, saturation, lightness) => {
    hue = hue / 360;
    saturation = saturation / 100;
    lightness = lightness / 100;
    let red, green, blue;

    const hue2rgb = (val1, val2, vH) => {
        vH = vH < 0 ? vH + 1 : vH > 1 ? vH - 1 : vH;

        if (vH < 1 / 6) {
            return val1 + (val2 - val1) * 6 * vH;
        }
        if (vH < 1 / 2) {
            return val2;
        }
        if (vH < 2 / 3) {
            return val1 + (val2 - val1) * (2 / 3 - vH) * 6;
        }
        return val1;
    };

    if (saturation === 0) {
        red = green = blue = lightness;
    } else {
        const val2 = lightness <= 0.5 ? lightness * (saturation + 1) : lightness + saturation - lightness * saturation;
        const val1 = lightness * 2 - val2;

        red = hue2rgb(val1, val2, hue + 1 / 3);
        green = hue2rgb(val1, val2, hue);
        blue = hue2rgb(val1, val2, hue - 1 / 3);
    }

    red = Math.round(red * 255);
    green = Math.round(green * 255);
    blue = Math.round(blue * 255);
    return [red, green, blue];
};

// 取颜色近似值
export const colorDistance = (rgb1, rgb2) => {
    let [r1, g1, b1] = rgb1;
    let [r2, g2, b2] = rgb2;

    let r = r1 - r2;
    let g = g1 - g2;
    let b = b1 - b2;

    // 权重算法
    let p = (r1 + r2) / 2;
    return Math.sqrt((2 + p / 256) * r * r + 4 * g * g + (2 + (255 - p) / 256) * b * b);

    // 432法
    // return Math.sqrt(2 * r * r + 4 * g * g + 3 * b * b);

    // 平方差法
    // return Math.sqrt(r * r + g * g + b * b);
};

// 取颜色近似值
export const getNearColorIndex = (rgb, list) => {
    const distance = list.map(i => colorDistance(rgb, i));
    const min = Math.min(...distance);
    const index = distance.indexOf(min);
    return index;
};
